home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / aux1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  26.3 KB  |  969 lines

  1. /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
  2. /* aux1.c */
  3. /* auxiliary functions for those in com.c, also see aux2.c and aux3.c */ 
  4.  
  5. #include "glob.h"
  6.  
  7.  
  8.  
  9. /* check to see if too much tunneling has been done in this level */
  10. void tunnelcheck()
  11. {
  12.   if ((Level->depth == 0 && Current_Environment != E_DLAIR) ||
  13.       Current_Environment == E_ASTRAL)
  14.     return;
  15.   Level->tunnelled++;
  16.   if ((Level->tunnelled) > LENGTH/4)
  17.     mprint("Dust and stone fragments fall on you from overhead.");
  18.   if ((Level->tunnelled) > LENGTH/2)
  19.     mprint("You hear groaning and creaking noises.");
  20.   if ((Level->tunnelled) > 3*LENGTH/4) 
  21.     mprint("The floor trembles and you hear a loud grinding screech.");
  22.   if ((Level->tunnelled) > LENGTH) {
  23.     mprint("With a scream of tortured stone, the entire dungeon caves in!!!");
  24.     gain_experience(5000);
  25.     if (Player.status[SHADOWFORM]) {
  26.       change_environment(E_COUNTRYSIDE);
  27.       switch (Country[Player.x][Player.y].base_terrain_type)
  28.       {
  29.     case CASTLE:
  30.     case STARPEAK:
  31.     case CAVES:
  32.     case VOLCANO:
  33.       Country[Player.x][Player.y].current_terrain_type = MOUNTAINS;
  34.       break;
  35.     case DRAGONLAIR:
  36.       Country[Player.x][Player.y].current_terrain_type = DESERT;
  37.       break;
  38.     case MAGIC_ISLE:
  39.       Country[Player.x][Player.y].current_terrain_type = CHAOS_SEA;
  40.       break;
  41.       }
  42.       Country[Player.x][Player.y].base_terrain_type = 
  43.       Country[Player.x][Player.y].current_terrain_type;
  44.       c_set(Player.x, Player.y, CHANGED);
  45.       print1("In your shadowy state, you float back up to the surface.");
  46.       return;
  47.     }
  48.     mprint("You are flattened into an unpleasant jellylike substance.");
  49.     p_death("dungeon cave-in");
  50.   }
  51. }
  52.  
  53. /* displays a room's name */
  54. void showroom(i)
  55. int i;
  56. {
  57.   strcpy(Str1,"");
  58.   strcpy(Str2,"");
  59.   switch(Current_Environment) {
  60.     case E_MANSION:
  61.       strcpy(Str2,"A luxurious mansion: ");
  62.       break;
  63.     case E_HOUSE:
  64.       strcpy(Str2,"A house: ");
  65.       break;
  66.     case E_HOVEL:
  67.       strcpy(Str2,"A hovel: ");
  68.       break;
  69.     case E_CITY:
  70.       strcpy(Str2,"The City of Rampart");
  71.       break;
  72.     case E_VILLAGE:
  73.       switch(Villagenum) {
  74.       case 1: strcpy(Str2,"The Village of Star View"); break;
  75.       case 2: strcpy(Str2,"The Village of Woodmere"); break;
  76.       case 3: strcpy(Str2,"The Village of Stormwatch"); break;
  77.       case 4: strcpy(Str2,"The Village of Thaumaris"); break;
  78.       case 5: strcpy(Str2,"The Village of Skorch"); break;
  79.       case 6: strcpy(Str2,"The Village of Whorfen"); break;
  80.       }
  81.       break;
  82.     case E_CAVES:
  83.       strcpy(Str2,"The Goblin Caves: ");
  84.       break;
  85.     case E_CASTLE:
  86.       strcpy(Str2,"The Archmage's Castle: ");
  87.       break;
  88.     case E_ASTRAL:
  89.       strcpy(Str2,"The Astral Plane: ");
  90.       break;
  91.     case E_VOLCANO:
  92.       strcpy(Str2,"The Volcano: ");
  93.       break;
  94.     case E_SEWERS:
  95.       strcpy(Str2,"The Sewers: ");
  96.       break;
  97.     case E_TACTICAL_MAP:
  98.       strcpy(Str2,"The Tactical Map ");
  99.       break;
  100.     default:
  101.       strcpy(Str2,"");
  102.       break;
  103.   }
  104.   if (Current_Environment == Current_Dungeon) {
  105.     strcpy(Str1,"Level ");
  106.     if (Level->depth < 10) {
  107.       Str1[6] = Level->depth + '0';
  108.       Str1[7] = 0;
  109.     }
  110.     else {
  111.       Str1[6] = (Level->depth / 10) + '0';
  112.       Str1[7] = (Level->depth % 10) + '0';
  113.       Str1[8] = 0;
  114.     }
  115.     strcat(Str1," (");
  116.     strcat(Str1,roomname(i));
  117.     strcat(Str1,")");
  118.   }
  119.   else if (strlen(Str2) == 0 || Current_Environment == E_MANSION ||
  120.       Current_Environment == E_HOUSE || Current_Environment == E_HOVEL)
  121.     strcpy(Str1,roomname(i));
  122.   strcat(Str2,Str1);
  123.   locprint(Str2);
  124. }
  125.  
  126.  
  127. int player_on_sanctuary()
  128. {
  129.   if ((Player.x==Player.sx) &&
  130.       (Player.y==Player.sy))
  131.     return(TRUE);
  132.   else {
  133.     if (Player.patron) {
  134.       if ((Level->site[Player.x][Player.y].locchar == ALTAR) &&
  135.       (Level->site[Player.x][Player.y].aux == Player.patron))
  136.     return(TRUE);
  137.       else return(FALSE);
  138.     }
  139.     else return(FALSE);
  140.   }
  141. }
  142.  
  143.  
  144. /* check a move attempt, maybe attack something, return TRUE if ok to move. */
  145. /* x y is the proposed place to move to */
  146. int p_moveable(x,y)
  147. int x,y;
  148. {
  149.   setgamestatus(SKIP_MONSTERS);
  150.   if (! inbounds(x,y)) return (FALSE);
  151.   else if (Player.status[SHADOWFORM]) {
  152.     switch(Level->site[x][y].p_locf) {
  153.       case L_CHAOS: case L_ABYSS: case L_VOID:
  154.     return confirmation();
  155.       default:
  156.     resetgamestatus(SKIP_MONSTERS);
  157.     return(TRUE);
  158.     }
  159.   }
  160.   else if (loc_statusp(x,y,SECRET)) {
  161.     if (!gamestatusp(FAST_MOVE)) print3("Ouch!");
  162.     return(FALSE);
  163.   }
  164.   else if (Level->site[x][y].creature != NULL) {
  165.     if (! gamestatusp(FAST_MOVE)) {
  166.       fight_monster(Level->site[x][y].creature);
  167.       resetgamestatus(SKIP_MONSTERS);
  168.       return(FALSE);
  169.     }
  170.     else return(FALSE);
  171.   }
  172.   else if ((Level->site[x][y].locchar == WALL) ||
  173.        (Level->site[x][y].locchar == STATUE) ||
  174.        (Level->site[x][y].locchar == PORTCULLIS) ||
  175.        (Level->site[x][y].locchar == CLOSED_DOOR) ||
  176.        (gamestatusp(FAST_MOVE) &&
  177.         ((Level->site[x][y].locchar == HEDGE) ||
  178.          (Level->site[x][y].locchar == LAVA) ||
  179.          (Level->site[x][y].locchar == ABYSS) ||
  180.          (Level->site[x][y].locchar == VOID_CHAR) ||
  181.          (Level->site[x][y].locchar == FIRE) ||
  182.          (Level->site[x][y].locchar == WHIRLWIND) ||
  183.          (Level->site[x][y].locchar == WATER) ||
  184.          (Level->site[x][y].locchar == LIFT) ||
  185.          (Level->site[x][y].locchar == TRAP)))) {
  186.     if (! gamestatusp(FAST_MOVE)) print3("Ouch!");
  187.     return(FALSE);
  188.   }
  189.   else if (optionp(CONFIRM)) {
  190.     if ((Level->site[x][y].locchar == HEDGE) ||
  191.     (Level->site[x][y].locchar == LAVA) ||
  192.     (Level->site[x][y].locchar == FIRE) ||
  193.     (Level->site[x][y].locchar == WHIRLWIND) ||
  194.     (Level->site[x][y].locchar == ABYSS) ||
  195.     (Level->site[x][y].locchar == VOID_CHAR) ||
  196.     (Level->site[x][y].locchar == WATER) ||
  197.     (Level->site[x][y].locchar == RUBBLE) ||
  198.     (Level->site[x][y].locchar == LIFT) ||
  199.     (Level->site[x][y].locchar == TRAP)) {
  200.       /* horses WILL go into water... */
  201.       if (gamestatusp(MOUNTED)) {
  202.     if (Level->site[x][y].locchar != WATER ||
  203.       Level->site[x][y].p_locf != L_WATER) {
  204.       print1("You can't convince your steed to continue.");
  205.       setgamestatus(SKIP_MONSTERS);
  206.       return(FALSE);
  207.     }
  208.     else return(TRUE);
  209.       }
  210.       else if (confirmation()) resetgamestatus(SKIP_MONSTERS);
  211.       else setgamestatus(SKIP_MONSTERS);
  212.       return(!gamestatusp(SKIP_MONSTERS));
  213.     }
  214.     else {
  215.       resetgamestatus(SKIP_MONSTERS);
  216.       return(TRUE);
  217.     }
  218.   }
  219.   else {
  220.     resetgamestatus(SKIP_MONSTERS);
  221.     return(TRUE);
  222.   }
  223. }
  224.  
  225.  
  226.  
  227. /* check a move attempt in the countryside */
  228. int p_country_moveable(x,y)
  229. int x,y;
  230. {
  231.   if (! inbounds(x,y)) return (FALSE);
  232.   else if (optionp(CONFIRM)) {
  233.     if ((Country[x][y].current_terrain_type == CHAOS_SEA) ||
  234.     (Country[x][y].current_terrain_type == MOUNTAINS))
  235.       return(confirmation());
  236.     else return(TRUE);
  237.   }
  238.   else return(TRUE);
  239. }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. /* search once particular spot */
  246. void searchat(x,y)
  247. int x,y;
  248. {
  249.   int i;
  250.   if (inbounds(x,y) && (random_range(3) || Player.status[ALERT])) {
  251.     if (loc_statusp(x,y,SECRET)) {
  252.       lreset(x,y,SECRET);
  253.       lset(x, y, CHANGED);
  254.       if ((Level->site[x][y].locchar==OPEN_DOOR) ||
  255.       (Level->site[x][y].locchar==CLOSED_DOOR)) {
  256.     mprint("You find a secret door!");
  257.     for(i=0;i<8;i++) {
  258.       lset(x+Dirs[0][i],y+Dirs[1][i],STOPS);
  259.       lset(x+Dirs[0][i], y+Dirs[1][i], CHANGED);
  260.     }
  261.       }
  262.       else mprint("You find a secret passage!");
  263.       drawvision(Player.x,Player.y);
  264.     }
  265.     if ((Level->site[x][y].p_locf >= TRAP_BASE) &&
  266.     (Level->site[x][y].locchar != TRAP) &&
  267.     (Level->site[x][y].p_locf <= TRAP_BASE+NUMTRAPS)) {
  268.       Level->site[x][y].locchar = TRAP;
  269.       lset(x, y, CHANGED);
  270.       mprint("You find a trap!");
  271.       drawvision(Player.x,Player.y);
  272.       resetgamestatus(FAST_MOVE);
  273.     }
  274.   }
  275. }
  276.  
  277.  
  278.  
  279. /* This is to be called whenever anything might change player performance in
  280.    melee, such as changing weapon, statistics, etc. */
  281. void calc_melee()
  282. {
  283.   calc_weight();
  284.  
  285.   Player.maxweight = (Player.str * Player.agi * 10);
  286.   Player.absorption = Player.status[PROTECTION];
  287.   Player.defense = 2 * statmod(Player.agi)+(Player.level/2);
  288.   Player.hit = Player.level + statmod(Player.dex)+1;
  289.   Player.dmg = statmod(Player.str)+3;
  290.   Player.speed = 5 - min(4,(statmod(Player.agi)/2));
  291.   if (Player.status[HASTED] > 0) Player.speed = Player.speed / 2;
  292.   if (Player.status[SLOWED] > 0) Player.speed = Player.speed * 2;
  293.   if (Player.itemweight > 0)
  294.     switch(Player.maxweight / Player.itemweight) {
  295.     case 0: Player.speed+=6; break;
  296.     case 1: Player.speed+=3; break;
  297.     case 2: Player.speed+=2; break;
  298.     case 3: Player.speed+=1; break;
  299.     }
  300.   
  301.   if (Player.status[ACCURATE]) Player.hit+=20;
  302.   if (Player.status[HERO]) Player.hit+=Player.dex;
  303.   if (Player.status[HERO]) Player.dmg+=Player.str;
  304.   if (Player.status[HERO]) Player.defense+=Player.agi;
  305.   if (Player.status[HERO]) Player.speed=Player.speed / 2;
  306.  
  307.   Player.speed = max(1,min(25,Player.speed));
  308.  
  309.   if (gamestatusp(MOUNTED)) {
  310.     Player.speed = 3;
  311.     Player.hit += 10;
  312.     Player.dmg += 10;
  313.   }
  314.  
  315.   /* weapon */
  316.   /* have to check for used since it could be a 2h weapon just carried
  317.      in one hand */
  318.   if (Player.possessions[O_WEAPON_HAND] != NULL) 
  319.     if (Player.possessions[O_WEAPON_HAND]->used &&
  320.     ((Player.possessions[O_WEAPON_HAND]->objchar==WEAPON)||
  321.      (Player.possessions[O_WEAPON_HAND]->objchar==MISSILEWEAPON))) {
  322.       Player.hit += 
  323.     Player.possessions[O_WEAPON_HAND]->hit + 
  324.       Player.possessions[O_WEAPON_HAND]->plus;
  325.       Player.dmg += 
  326.     Player.possessions[O_WEAPON_HAND]->dmg + 
  327.       Player.possessions[O_WEAPON_HAND]->plus;
  328.     }
  329.   
  330.   /* shield or defensive weapon */
  331.   if (Player.possessions[O_SHIELD] != NULL) {
  332.     Player.defense += 
  333.       Player.possessions[O_SHIELD]->aux + 
  334.     Player.possessions[O_SHIELD]->plus;
  335.   }
  336.   
  337.   /* armor */
  338.   if (Player.possessions[O_ARMOR] != NULL) {
  339.     Player.absorption += Player.possessions[O_ARMOR]->dmg;
  340.     Player.defense += 
  341.       Player.possessions[O_ARMOR]->plus - 
  342.     Player.possessions[O_ARMOR]->aux;
  343.   }
  344.  
  345.   if (strlen(Player.meleestr) > 2*maneuvers())
  346.     default_maneuvers();
  347.   comwinprint();
  348.   showflags();
  349.   dataprint();
  350. }
  351.  
  352.  
  353. /* player attacks monster m */
  354. void fight_monster(m)
  355. struct monster *m;
  356. {
  357.   int hitmod = 0;
  358.   int reallyfight = TRUE;
  359.  
  360.   if (Player.status[AFRAID]) {
  361.     print3("You are much too afraid to fight!");
  362.     reallyfight = FALSE;
  363.   }
  364.   else if (player_on_sanctuary()) {
  365.     print3("You restrain yourself from desecrating this holy place.");
  366.     reallyfight = FALSE;
  367.   }
  368.   else if (Player.status[SHADOWFORM]) {
  369.     print3("Your attack has no effect in your shadowy state.");
  370.     reallyfight = FALSE;
  371.   }
  372.   else if ((Player.status[BERSERK]<1) && (! m_statusp(m,HOSTILE))) {
  373.     if (optionp(BELLICOSE)) reallyfight = TRUE;
  374.     else reallyfight = confirmation();
  375.   }
  376.   else reallyfight = TRUE;
  377.   
  378.   if (reallyfight) {
  379.  
  380.     if (Lunarity == 1) hitmod += Player.level;
  381.     else if (Lunarity == -1) hitmod -= (Player.level / 2);
  382.  
  383.     if (! m->attacked) Player.alignment -= 2; /* chaotic action */
  384.     m_status_set(m,AWAKE);
  385.     m_status_set(m,HOSTILE);
  386.     m->attacked = TRUE;
  387.     Player.hit += hitmod;
  388.     tacplayer(m);
  389.     Player.hit -= hitmod;
  390.   }
  391. }
  392.  
  393.  
  394.  
  395.  
  396. /* Attempt to break an object o */
  397. int damage_item(o)
  398. pob o;     
  399. {
  400.   int i;
  401.   /* special case -- break star gem */
  402.   if (o->id == ARTIFACTID+21) {
  403.     print1("The Star Gem shatters into a million glistening shards....");
  404.     if (Current_Environment == E_STARPEAK) {
  405.       if (! gamestatusp(KILLED_LAWBRINGER))
  406.     print2("You hear an agonizing scream of anguish and despair.");
  407.       morewait();
  408.       print1("A raging torrent of energy escapes in an explosion of magic!");
  409.       print2("The energy flows to the apex of Star Peak where there is");
  410.       morewait();
  411.       clearmsg();
  412.       print1("an enormous explosion!");
  413.       morewait();
  414.       annihilate(1);
  415.       print3("You seem to gain strength in the chaotic glare of magic!");
  416.       Player.str = Player.maxstr + 5;
  417.       Player.pow = Player.maxpow + 5;
  418.       Player.alignment -= 200;
  419.       dispose_lost_objects(1,o);
  420.     }
  421.     else {
  422.       morewait();
  423.       print1("The shards coalesce back together again, and vanish");
  424.       print2("with a muted giggle.");
  425.       dispose_lost_objects(1,o);
  426.     }
  427.     return 1;
  428.   }
  429.   else {
  430.     if (o->fragility < random_range(30)) {
  431.       if (o->objchar == STICK) {
  432.     strcpy(Str1,"Your ");
  433.     strcat(Str1,(o->blessing >= 0 ? o->truename : o->cursestr));
  434.     strcat(Str1," explodes!");
  435.     print1(Str1);
  436.     morewait();
  437.     if (o->charge < 1)
  438.       nprint1(" Fzzz... Out of Power... Oh well...");
  439.     else {
  440.       nprint1(" Ka-Blamm!!!");
  441.       /* general case. Some sticks will eventually do special things */
  442.       morewait();
  443.       manastorm(Player.x, Player.y, o->charge*o->level*10);
  444.       dispose_lost_objects(1,o);
  445.     }
  446.     return 1;
  447.       }
  448.       else if ((o->blessing > 0) && (o->level > random_range(10))) {
  449.     strcpy(Str1,"Your ");
  450.     strcat(Str1,itemid(o));
  451.     strcat(Str1," glows strongly.");
  452.     print1(Str1);
  453.     return 0;
  454.       }
  455.       else if ((o->blessing < -1) && (o->level > random_range(10))) {
  456.     strcpy(Str1,"You hear an evil giggle from your ");
  457.     strcat(Str1,itemid(o));
  458.     print1(Str1);
  459.     return 0;
  460.       }
  461.       else if (o->plus > 0) {
  462.     strcpy(Str1,"Your ");
  463.     strcat(Str1,itemid(o));
  464.     strcat(Str1," glows and then fades.");
  465.     print1(Str1);
  466.     o->plus--;
  467.     return 0;
  468.       }
  469.       else {
  470.     if (o->blessing > 0) print1("You hear a faint despairing cry!");
  471.     else if (o->blessing < 0) print1("You hear an agonized scream!");
  472.     strcpy(Str1,"Your ");
  473.     strcat(Str1,itemid(o));
  474.     strcat(Str1," shatters in a thousand lost fragments!");
  475.     print2(Str1);
  476.     morewait();
  477.     dispose_lost_objects(1,o);
  478.     return 1;
  479.       }
  480.     }
  481.     return 0;
  482.   }
  483. }
  484.       
  485.       
  486.  
  487.  
  488.  
  489.  
  490.  
  491. /* do dmg points of damage of type dtype, from source fromstring */
  492. void p_damage(dmg,dtype,fromstring)
  493. int dmg,dtype;
  494. char *fromstring;
  495. {
  496.   if (! p_immune(dtype)) {
  497.     if (gamestatusp(FAST_MOVE)) {
  498.       drawvision(Player.x,Player.y);
  499.       resetgamestatus(FAST_MOVE);
  500.     }
  501.     if (dtype == NORMAL_DAMAGE) Player.hp -= max(1,(dmg-Player.absorption));
  502.     else Player.hp -= dmg;
  503.     if (Player.hp < 1) p_death(fromstring);
  504.   }
  505.   else mprint("You resist the effects!");
  506.   dataprint();
  507. }
  508.  
  509. /* game over, you lose! */
  510. void p_death(fromstring)
  511. char *fromstring;
  512. {
  513.   Player.hp = -1;
  514.   print3("You died!");
  515.   morewait();
  516.   display_death(fromstring);
  517. #ifdef SAVE_LEVELS
  518.   kill_all_levels();
  519. #endif
  520.   endgraf();
  521.   exit(0);
  522. }
  523.  
  524.  
  525. /* move the cursor around, like for firing a wand, sets x and y to target */
  526. void setspot(x,y)
  527. int *x,*y;
  528. {
  529.   char c = ' ';
  530.   mprint("Targeting.... ? for help");
  531.   omshowcursor(*x,*y);
  532.   while ((c != '.') && (c != ESCAPE)) {
  533.     c = lgetc();
  534.     switch(c) {
  535.       case 'h':case '4': movecursor(x,y,-1,0);  break;
  536.       case 'j':case '2': movecursor(x,y,0,1);  break;
  537.       case 'k':case '8': movecursor(x,y,0,-1);  break;
  538.       case 'l':case '6': movecursor(x,y,1,0);  break;
  539.       case 'b':case '1': movecursor(x,y,-1,1);  break;
  540.       case 'n':case '3': movecursor(x,y,1,1);  break;
  541.       case 'y':case '7': movecursor(x,y,-1,-1);  break;
  542.       case 'u':case '9': movecursor(x,y,1,-1);  break;
  543.       case '?':
  544.     clearmsg();
  545.     mprint("Use vi keys or numeric keypad to move cursor to target.");
  546.     mprint("Hit the '.' key when done, or ESCAPE to abort.");
  547.     break;
  548.     }
  549.   }
  550.   if (c==ESCAPE) *x = *y= ABORT;
  551.   screencheck(Player.y);
  552. }
  553.  
  554.  
  555. /* get a direction: return index into Dirs array corresponding to direction */
  556. int getdir()
  557. {
  558.   while (1) {
  559.     mprint("Select direction [hjklyubn, ESCAPE to quit]: ");
  560.     switch (mgetc()) {
  561.     case '4':
  562.     case 'h':
  563.     case 'H': return(5);
  564.     case '2':
  565.     case 'j':
  566.     case 'J': return(6);
  567.     case '8':
  568.     case 'k':
  569.     case 'K': return(7);
  570.     case '6':
  571.     case 'l':
  572.     case 'L': return(4);
  573.     case '7':
  574.     case 'y':
  575.     case 'Y': return(3);
  576.     case '9':
  577.     case 'u':
  578.     case 'U': return(1);
  579.     case '1':
  580.     case 'b':
  581.     case 'B': return(2);
  582.     case '3':
  583.     case 'n':
  584.     case 'N': return(0);
  585.     case ESCAPE: return(ABORT);
  586.     default: print3("That's not a direction! ");
  587.     }
  588.   }
  589. }
  590.  
  591.  
  592.  
  593. /* functions describes monster m's state for examine function */      
  594. char *mstatus_string(m)
  595. struct monster *m;
  596. {
  597.   if (m_statusp(m, M_INVISIBLE) && !Player.status[TRUESIGHT])
  598.     strcpy(Str2, "Some invisible creature");
  599.   else if (m->uniqueness == COMMON) {
  600.     if (m->hp < Monsters[m->id].hp / 3)
  601.       strcpy(Str2,"a grievously injured ");
  602.     else if (m->hp < Monsters[m->id].hp / 2)
  603.       strcpy(Str2,"a severely injured ");
  604.     else if (m->hp < Monsters[m->id].hp)
  605.       strcpy(Str2,"an injured ");
  606.     else strcpy(Str2,getarticle(m->monstring));
  607.     if (m->level > Monsters[m->id].level) {
  608.       strcat(Str2," (level ");
  609.       strcat(Str2,wordnum(m->level+1-Monsters[m->id].level));
  610.       strcat(Str2,") ");
  611.     }
  612.     strcat(Str2,m->monstring);
  613.   }
  614.   else {
  615.     strcpy(Str2,m->monstring);
  616.     if (m->hp < Monsters[m->id].hp / 3)
  617.       strcat(Str2," who is grievously injured ");
  618.     else if (m->hp < Monsters[m->id].hp / 2)
  619.       strcat(Str2," who is severely injured ");
  620.     else if (m->hp < Monsters[m->id].hp)
  621.       strcat(Str2," who is injured ");
  622.   }
  623.   return(Str2);
  624. }
  625.  
  626.  
  627.  
  628.  
  629. /* for the examine function */
  630. void describe_player()
  631. {
  632.   if (Player.hp < (Player.maxhp /5))
  633.     print1("A grievously injured ");
  634.   else if (Player.hp < (Player.maxhp /2))
  635.     print1("A seriously wounded ");
  636.   else if (Player.hp < Player.maxhp)
  637.     print1("A somewhat bruised ");
  638.   else print1("A fit ");
  639.  
  640.   if (Player.status[SHADOWFORM])
  641.     nprint1("shadow");
  642.   else
  643.     nprint1(levelname(Player.level));
  644.   nprint1(" named ");
  645.   nprint1(Player.name);
  646.   if (gamestatusp(MOUNTED))
  647.     nprint1(" (riding a horse.)");
  648. }
  649.  
  650.  
  651. /* access to player experience... */
  652. /* share out experience among guild memberships */
  653. void gain_experience(amount)
  654. int amount;
  655. {
  656.   int i,count=0,share;
  657.   Player.xp += (long) amount;
  658.   gain_level(); /* actually, check to see if should gain level */
  659.   for(i=0;i<NUMRANKS;i++)
  660.     if (Player.guildxp[i] > 0) count++;
  661.   share = amount/(max(count,1));
  662.   for(i=0;i<NUMRANKS;i++)
  663.     if (Player.guildxp[i] > 0) Player.guildxp[i]+=share;
  664. }
  665.  
  666. /* try to hit a monster in an adjacent space. If there are none
  667.    return FALSE. Note if you're berserk you get to attack ALL
  668.    adjacent monsters! */
  669. int goberserk()
  670. {
  671.   int wentberserk=FALSE,i;
  672.   char meleestr[80];
  673.   strcpy(meleestr,Player.meleestr);
  674.   strcpy(Player.meleestr,"lLlClH");
  675.   for(i=0;i<8;i++)
  676.     if (Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature
  677.     != NULL) {
  678.       wentberserk=TRUE;
  679.       fight_monster(Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature);
  680.       morewait();
  681.     }
  682.   strcpy(Player.meleestr,meleestr);
  683.   return(wentberserk);
  684. }
  685.  
  686. /* identifies a trap for examine() by its aux value */
  687. char *trapid(trapno)
  688. int trapno;
  689. {
  690.   switch (trapno) {
  691.   case L_TRAP_SIREN:return("A siren trap");
  692.   case L_TRAP_DART:return("A dart trap");
  693.   case L_TRAP_PIT:return("A pit");
  694.   case L_TRAP_SNARE:return("A snare");
  695.   case L_TRAP_BLADE:return("A blade trap");
  696.   case L_TRAP_FIRE:return("A fire trap");
  697.   case L_TRAP_TELEPORT:return("A teleport trap");
  698.   case L_TRAP_DISINTEGRATE:return("A disintegration trap");
  699.   case L_TRAP_DOOR:return("A trap door");
  700.   case L_TRAP_MANADRAIN:return("A manadrain trap");
  701.   case L_TRAP_ACID:return("An acid shower trap");
  702.   case L_TRAP_SLEEP_GAS:return("A sleep gas trap");
  703.   case L_TRAP_ABYSS:return("A concealed entrance to the abyss");
  704.   default: return("A completely inoperative trap.");
  705.   }
  706. }
  707.  
  708.  
  709. /* checks current food status of player, every hour, and when food is eaten */
  710. void foodcheck()
  711. {
  712.   if (Player.food > 48) {
  713.     print3("You vomit up your huge meal.");
  714.     Player.food = 12;
  715.   }
  716.   else if (Player.food == 30) 
  717.     print3("Time for a smackerel of something.");
  718.   else if (Player.food == 20) 
  719.     print3("You feel hungry.");
  720.   else if (Player.food == 12) 
  721.     print3("You are ravenously hungry.");
  722.   else if (Player.food == 3) {
  723.     print3("You feel weak.");
  724.     if (gamestatusp(FAST_MOVE)) {
  725.       drawvision(Player.x,Player.y);
  726.       resetgamestatus(FAST_MOVE);
  727.     }
  728.   }
  729.   else if (Player.food < 0) {
  730.     if (gamestatusp(FAST_MOVE)) {
  731.       drawvision(Player.x,Player.y);
  732.       resetgamestatus(FAST_MOVE);
  733.     }
  734.     print3("You're starving!");
  735.     p_damage(-5*Player.food,UNSTOPPABLE,"starvation");
  736.   }
  737.   showflags();
  738. }
  739.  
  740.  
  741.  
  742.  
  743. /* see whether room should be illuminated */
  744. void roomcheck()
  745. {
  746.   static int oldroomno = -1;
  747. #ifdef MSDOS
  748.   static int oldlevel = -1;
  749. #else
  750.   static plv oldlevel = NULL;
  751. #endif
  752.   int roomno = Level->site[Player.x][Player.y].roomnumber;
  753.  
  754.   if ((roomno == RS_CAVERN) ||
  755.       (roomno == RS_SEWER_DUCT) || 
  756.       (roomno == RS_KITCHEN) ||
  757.       (roomno == RS_BATHROOM) ||
  758.       (roomno == RS_BEDROOM) ||
  759.       (roomno == RS_DININGROOM) ||
  760.       (roomno == RS_CLOSET) ||
  761.       (roomno > ROOMBASE))
  762.     if ((! loc_statusp(Player.x,Player.y,LIT)) && 
  763.     (! Player.status[BLINDED]) &&
  764.     (Player.status[ILLUMINATION] || (difficulty() < 6))) {
  765.       showroom(Level->site[Player.x][Player.y].roomnumber);
  766.       spreadroomlight(Player.x,Player.y,roomno);
  767.       levelrefresh();
  768.     }
  769.   if ((oldroomno != roomno) ||
  770. #ifdef MSDOS
  771.       (oldlevel != Level->depth)) {
  772. #else
  773.       (oldlevel != Level)) {
  774. #endif
  775.     showroom(roomno);
  776.     oldroomno = roomno;
  777. #ifdef MSDOS
  778.     oldlevel = Level->depth;
  779. #else
  780.     oldlevel = Level;
  781. #endif
  782.   }
  783. }
  784.  
  785.  
  786.  
  787.  
  788.  
  789. /* ask for mercy */
  790. void surrender(m)
  791. struct monster *m;
  792. {
  793.   int i;
  794.   long bestitem,bestvalue;
  795.  
  796.   switch(random_range(4)) {
  797.   case 0: print1("You grovel at the monster's feet..."); break;
  798.   case 1: print1("You cry 'uncle'!"); break;
  799.   case 2: print1("You beg for mercy."); break;
  800.   case 3: print1("You yield to the monster."); break;
  801.   }
  802.   if (m->id == ML0+3) {
  803.     if (m_statusp(m,HOSTILE))
  804.       monster_talk(m);
  805.     else {
  806.       print2("The guard (bored): Have you broken a law? [yn] ");
  807.       if (ynq2() == 'y') {
  808.     print2("The guard grabs you, and drags you to court.");
  809.     morewait();
  810.     send_to_jail();
  811.       }
  812.       else print2("Then don't bother me. Scat!");
  813.     }
  814.   }
  815.   else if ((m->talkf==M_NO_OP) ||
  816.        (m->talkf==M_TALK_STUPID))
  817.     print3("Your plea is ignored.");
  818.   else  {
  819.     morewait();
  820.     print1("Your surrender is accepted.");
  821.     if (Player.cash > 0) nprint1(" All your gold is taken....");
  822.     Player.cash = 0;
  823.     bestvalue = 0;
  824.     bestitem = ABORT;
  825.     for (i=1;i<MAXITEMS;i++)
  826.       if (Player.possessions[i] != NULL)
  827.     if (bestvalue < true_item_value(Player.possessions[i])) {
  828.           bestitem = i;
  829.           bestvalue = true_item_value(Player.possessions[i]);
  830.         }
  831.     if (bestitem != ABORT) {
  832.       print2("You also give away your best item... ");
  833.       nprint2(itemid(Player.possessions[bestitem]));
  834.       nprint2(".");
  835.       morewait();
  836.       givemonster(m,Player.possessions[bestitem]);
  837.       morewait(); /* msgs come from givemonster */
  838.       conform_unused_object(Player.possessions[bestitem]);
  839.       Player.possessions[bestitem] = NULL;
  840.     }
  841.     print2("You feel less experienced... ");
  842.     Player.xp = max(0,Player.xp - m->xpv);
  843.     nprint2("The monster seems more experienced!");
  844.     m->level = (min(10,m->level+1));
  845.     m->hp += m->level*20;
  846.     m->hit += m->level;
  847.     m->dmg += m->level;
  848.     m->ac += m->level;
  849.     m->xpv += m->level*10;
  850.     morewait();
  851.     clearmsg();
  852.     if ((m->talkf == M_TALK_EVIL) && random_range(10)) {
  853.       print1("It continues to attack you, laughing evilly!");
  854.       m_status_set(m,HOSTILE);
  855.       m_status_reset(m,GREEDY);
  856.     }
  857.     else if (m->id == ML0+0 || m->id == ML0+3)
  858.       print1("It continues to attack you. ");
  859.     else {
  860.       print1("The monster leaves, chuckling to itself....");
  861.       m_teleport(m);
  862.     }
  863.   }
  864.   dataprint();
  865. }
  866.  
  867.  
  868. /* threaten a monster */
  869. void threaten(m)
  870. struct monster *m;
  871. {
  872.   char response;
  873.   switch(random_range(4)) {
  874.   case 0:mprint("You demand that your opponent surrender!"); break;
  875.   case 1:mprint("You threaten to do bodily harm to it."); break;
  876.   case 2:mprint("You attempt to bluster it into submission."); break;
  877.   case 3:mprint("You try to cow it with your awesome presence."); break;
  878.   }
  879.   if (! m_statusp(m,HOSTILE)) {
  880.     print3("You only annoy it with your futile demand.");
  881.     m_status_set(m,HOSTILE);
  882.   }
  883.   else if (((m->level*2 > Player.level) && (m->hp > Player.dmg)) || 
  884.        (m->uniqueness != COMMON))
  885.     print1("It sneers contemptuously at you.");
  886.   else if ((m->talkf != M_TALK_GREEDY) &&
  887.        (m->talkf != M_TALK_HUNGRY) &&
  888.        (m->talkf != M_TALK_EVIL) &&
  889.        (m->talkf != M_TALK_MAN) &&
  890.        (m->talkf != M_TALK_BEG) &&
  891.        (m->talkf != M_TALK_THIEF) &&
  892.        (m->talkf != M_TALK_MERCHANT) &&
  893.        (m->talkf != M_TALK_IM)) 
  894.     print1("Your demand is ignored");
  895.   else {
  896.     print1("It yields to your mercy.");
  897.     Player.alignment+=3;
  898.     print2("Kill it, rob it, or free it? [krf] ");
  899.     do response = (char) mcigetc();
  900.     while ((response != 'k')&&(response != 'r')&&(response !='f'));
  901.     if (response == 'k') {
  902.       m_death(m);
  903.       print2("You treacherous rogue!");
  904.       Player.alignment -= 13;
  905.     }
  906.     else if (response == 'r') {
  907.       Player.alignment-=2;
  908.       print2("It drops its treasure and flees.");
  909.       m_dropstuff(m);
  910.       m->hp = -1;
  911.       Level->site[m->x][m->y].creature = NULL;
  912.       putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
  913.     }
  914.     else {
  915.       Player.alignment+=2;
  916.       print2("'If you love something set it free ... '");
  917.       if (random_range(100)==13) {
  918.     morewait();
  919.     print2("'...If it doesn't come back, hunt it down and kill it.'");
  920.       }
  921.       print3("It departs with a renewed sense of its own mortality.");
  922.       m->hp = -1;
  923.       Level->site[m->x][m->y].creature = NULL;
  924.       putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
  925.     }
  926.   }
  927. }
  928.  
  929. /* name of the player's experience level */
  930. char *levelname(level)
  931. int level;
  932. {
  933.   switch(level) {
  934.   case 0:strcpy(Str3,"neophyte");break;
  935.   case 1:strcpy(Str3,"beginner");break;
  936.   case 2:strcpy(Str3,"tourist");break;
  937.   case 3:strcpy(Str3,"traveller");break;
  938.   case 4:strcpy(Str3,"wayfarer");break;
  939.   case 5:strcpy(Str3,"peregrinator");break;
  940.   case 6:strcpy(Str3,"wanderer");break;
  941.   case 7:strcpy(Str3,"hunter");break;
  942.   case 8:strcpy(Str3,"scout");break;
  943.   case 9:strcpy(Str3,"trailblazer");break;
  944.   case 10:strcpy(Str3,"discoverer");break;
  945.   case 11:strcpy(Str3,"explorer");break;
  946.   case 12:strcpy(Str3,"senior explorer");break;
  947.   case 13:strcpy(Str3,"ranger");break;
  948.   case 14:strcpy(Str3,"ranger captain");break;
  949.   case 15:strcpy(Str3,"ranger knight");break;
  950.   case 16:strcpy(Str3,"adventurer");break;
  951.   case 17:strcpy(Str3,"experienced adventurer");break;
  952.   case 18:strcpy(Str3,"skilled adventurer");break;
  953.   case 19:strcpy(Str3,"master adventurer");break;
  954.   case 20:strcpy(Str3,"hero");break;
  955.   case 21:strcpy(Str3,"superhero");break;
  956.   case 22:strcpy(Str3,"demigod");break;
  957.   default:
  958.     if (level < 100) {
  959.       strcpy(Str3,"Order ");
  960.       Str3[6] = ((level/10)-2) + '0';
  961.       Str3[7] = 0;
  962.       strcat(Str3," Master of Omega");
  963.     }
  964.     else strcpy(Str3,"Ultimate Master of Omega");
  965.     break;
  966.   }
  967.   return(Str3);
  968. }
  969.